package com.gitee.helioz.openai.api.dto.chat;

import com.google.gson.annotations.SerializedName;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;

/**
 * 〈聊天式对话补全请求〉
 *
 * @author <a href="https://gitee.com/helioz">Morning Starr</a>
 */
@Data
public class ChatCompletionRequest {

    /**
     * 模型ID
     * <pre>必填</pre>
     */
    private String model;
    /**
     * 描述对话的消息列表
     * <pre>必填</pre>
     */
    private List<ChatMessage> messages;
    /**
     * 控制生成文本的随机性。较高的值会使生成的文本更加随机，较低的值会使生成的文本更加确定性。
     * 取值范围是 0 到 2，通常推荐使用默认值 1.0，更改时与top_p二选一不要同时更改两者
     * <pre>选填</pre>
     */
    private Double temperature;
    /**
     * 用于控制生成文本中下一个单词的选择范围，取值范围是 0 到 1，通常推荐使用默认值 1，
     * 当设置较小的值时，生成的文本可能会更加集中在高概率的单词上，从而变得更加确定性。
     * 当设置较大的值时，生成的文本可能会更加随机，因为更多的低概率单词也有可能被考虑作为下一个单词的选择，
     * 更改时与temperature二选一不要同时更改两者
     * <pre>选填</pre>
     */
    @SerializedName("top_p")
    private Double topP;
    /**
     * 用于指定生成文本的数量，即一次请求中生成多少个文本。默认值为 1
     * <pre>选填</pre>
     */
    private Integer n;
    /**
     * 用于控制是否将生成的文本以流的形式逐步返回，而不是一次性返回完整的生成结果，默认值为 false，
     * 当 stream 参数设置为 true 时，生成的文本将以流的形式逐步返回，每次生成一段文本时都会调用 API 返回一个片段，
     * 可以通过处理这些片段来逐步构建完整的生成结果。这对于生成较长的文本或者需要逐步展示给用户的场景非常有用，比如实时聊天应用、逐步展示生成的代码等。
     * 当 stream 参数设置为 false（默认值）时，生成的文本将一次性返回完整的生成结果，不会以流的形式逐步返回。
     * <pre>选填</pre>
     */
    private Boolean stream;
    /**
     * 默认值为 null，最多4个序列，用于指定生成文本的停止条件，即生成文本中包含了指定的停止字符串时，生成过程会立即停止，
     * 注意，停止字符串是区分大小写的，因此请确保指定的停止字符串与生成文本中的大小写一致
     * <pre>例如，如果在生成电子邮件的过程中，希望在生成结果中包含了"@"这个停止字符串时立即停止生成，可以将 stop 参数设置为 "@"</pre>
     * <pre>选填</pre>
     */
    private List<String> stop;
    /**
     * 用于限制生成文本的最大长度。如果生成的文本长度超过了指定的最大长度，将会被截断。
     * 注意，设置过小的 max_tokens 值可能导致生成的文本不完整或不合理，而设置过大的 max_tokens 值可能导致生成的文本过长，影响生成效果和性能。
     * 因此，需要根据实际需求合理设置 max_tokens 参数的值。
     * <pre>选填</pre>
     */
    @SerializedName("max_tokens")
    private Integer maxTokens;
    /**
     * 默认值为 0。范围(-2.0, 2.0)。
     * 用于设置存在惩罚的值。它可以在对话中控制助理生成的回复的多样性。存在惩罚是一种控制生成文本中重复性的技术。
     * 当 presence_penalty 的值越大时，助理生成的回复中相似的文本越可能被惩罚，从而生成更加多样化的结果。
     * <p>
     * 例如，如果在请求中设置了 presence_penalty 为 0.8，那么生成的助理回复会更加多样化，相似的文本会被惩罚，从而生成更加丰富和多样的对话回复。
     * 如果将 presence_penalty 设置为较小的值，例如 0.2，那么生成的结果可能会更加倾向于生成重复性较高的文本。
     * </p>
     * <pre>选填</pre>
     */
    @SerializedName("presence_penalty")
    private Integer presencePenalty;
    /**
     * 默认值为 0。范围(-2.0, 2.0)。
     * 用于设置频率惩罚的值。它可以在对话中控制助理生成的回复中使用相同词汇的频率。频率惩罚是一种控制生成文本中重复词汇的技术。
     * 当 frequency_penalty 的值越大时，助理生成的回复中相同词汇的使用频率越低，从而生成更加多样化的结果。
     * <p>
     * 例如，如果在请求中设置了 frequency_penalty 为 0.8，那么生成的助理回复中相同词汇的使用频率会较低，从而生成更加丰富和多样的对话回复。
     * 如果将 frequency_penalty 设置为较小的值，例如 0.2，那么生成的结果中相同词汇的使用频率可能会较高。
     * </p>
     * <pre>选填</pre>
     */
    @SerializedName("frequency_penalty")
    private Integer frequencyPenalty;
    /**
     * 默认值为 null。用于设置生成文本中的偏置（bias）。
     * 通过一个列表来指定不同角色的偏置值，从而在生成回复时引导助理偏向特定角色的回复。每个角色都可以分配一个偏置值，该值越高表示助理在生成文本时更倾向于使用该角色的语言。
     * 偏置值是用来控制对话中角色之间的平衡的工具，可以在生成回复时引导助理的表现方式。
     * <pre>
     * 例如，可以使用正数的偏置值来增加特定角色的影响力，或者使用负数的偏置值来减少特定角色的影响力。
     * logit_bias 参数是一个包含角色和对应偏置值的字典或映射。例如，以下是一个设置角色偏置值的示例：
     * "logit_bias": {
     *   "system": 0.5,
     *   "user": 0.0,
     *   "assistant": -0.5
     * }
     * 在这个示例中，给予了 "system" 角色一个正数偏置值 0.5，给予了 "user" 角色一个零偏置值，给予了 "assistant" 角色一个负数偏置值 -0.5。
     * 这样生成的回复可能会更倾向于使用 "system" 角色的语言，少使用 "assistant" 角色的语言。
     * </pre>
     * <pre>选填</pre>
     */
    @SerializedName("logit_bias")
    private Map<String, Double> logitBias;

    /**
     * 代表终端用户的唯一标识符，可以帮助OpenAI监控和检测滥用
     * <pre>必填</pre>
     */
    private String user;

    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    @Data
    public static class ChatMessage {
        /**
         * 此消息作者的角色。
         * <pre>
         * "system" 表示系统角色，用于发送系统级的指令或控制信息。
         * "user" 表示用户角色，用于用户输入的对话消息。
         * "assistant" 表示助理角色，用于生成助理的回复
         * </pre>
         * 通过在对话消息中指定不同的 role，可以控制对话中不同角色的交互行为和生成结果。
         * 例如，可以使用 "system" 角色发送指令来控制生成文本的样式或行为，使用 "user" 角色输入用户的对话内容，使用 "assistant" 角色生成助理的回复。
         * <pre>必填</pre>
         * @see com.gitee.helioz.openai.common.constants.MessageRoleEnum
         */
        private String role;
        /**
         * 消息的内容
         * <pre>必填</pre>
         */
        private String content;

        /**
         * 此消息作者的姓名。可以包含a-z、A-Z、0-9和下划线，最大长度为64个字符
         * <pre>选填</pre>
         */
        private String name;
    }

}
